use crate::{ConfigLoader, ConfigSource, ConfigFormat, RustCloudConfig};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::watch;
use tokio::task::JoinHandle;
use tracing::{info, warn, error};

/// 配置管理器 - 负责配置的热加载和管理
pub struct ConfigManager {
    sources: Vec<ConfigSource>,
    current_config: watch::Sender<Arc<RustCloudConfig>>,
    reload_handle: Option<JoinHandle<()>>,
    reload_interval: Duration,
}

impl ConfigManager {
    /// 创建新的配置管理器
    pub fn new(reload_interval: Duration) -> (Self, watch::Receiver<Arc<RustCloudConfig>>) {
        let (tx, rx) = watch::channel(Arc::new(RustCloudConfig::default()));

        let manager = Self {
            sources: Vec::new(),
            current_config: tx,
            reload_handle: None,
            reload_interval,
        };

        (manager, rx)
    }

    /// 添加配置源
    pub fn add_source(&mut self, source: ConfigSource) {
        self.sources.push(source);
    }

    /// 初始加载配置
    pub async fn load_config(&mut self) -> Result<Arc<RustCloudConfig>, String> {
        let config = self.load_from_sources().await?;
        let config = Arc::new(config);
        self.current_config.send(config.clone()).map_err(|_| "Failed to send config")?;
        Ok(config)
    }

    /// 从所有配置源加载配置
    async fn load_from_sources(&self) -> Result<RustCloudConfig, String> {
        // 按优先级排序配置源
        let mut sources = self.sources.clone();
        sources.sort_by_key(|s| s.priority());
        sources.reverse();

        let mut merged_config = None;

        for source in sources {
            match self.load_from_source(&source).await {
                Ok(config) => {
                    merged_config = Some(config);
                    info!("Loaded config from source: {}", source);
                }
                Err(e) => {
                    warn!("Failed to load config from source {}: {}", source, e);
                    continue;
                }
            }
        }

        merged_config.ok_or_else(|| "No valid configuration sources found".to_string())
    }

    /// 从单个配置源加载配置
    async fn load_from_source(&self, source: &ConfigSource) -> Result<RustCloudConfig, String> {
        match source {
            ConfigSource::File { path, format: _ } => {
                let loader = ConfigLoader::from_path(path)?;
                loader.load()
            }
            ConfigSource::Environment { prefix } => {
                self.load_from_env(prefix)
            }
            ConfigSource::Remote { url, format, auth } => {
                self.load_from_remote(url, *format, auth).await
            }
            ConfigSource::Embedded { config } => Ok(config.clone()),
        }
    }

    /// 从环境变量加载配置
    fn load_from_env(&self, _prefix: &str) -> Result<RustCloudConfig, String> {
        // 简化的环境变量加载实现
        // 实际应用中可能需要更复杂的解析逻辑
        let config = RustCloudConfig::default();
        // 这里可以实现环境变量到配置的映射
        Ok(config)
    }

    /// 从远程配置源加载配置
    async fn load_from_remote(&self, _url: &str, _format: ConfigFormat, _auth: &Option<crate::RemoteAuth>) -> Result<RustCloudConfig, String> {
        // 简化的远程加载实现
        Err("Remote configuration loading not implemented yet".to_string())
    }

    /// 启动配置热加载
    pub async fn start_hot_reload(&mut self) {
        if self.reload_handle.is_some() {
            return;
        }

        let sources = self.sources.clone();
        let config_sender = self.current_config.clone();
        let reload_interval = self.reload_interval;

        let handle = tokio::spawn(async move {
            let mut interval_timer = tokio::time::interval(reload_interval);
            
            loop {
                interval_timer.tick().await;
                
                let manager = ConfigManager {
                    sources: sources.clone(),
                    current_config: config_sender.clone(),
                    reload_handle: None,
                    reload_interval,
                };
                
                match manager.load_from_sources().await {
                    Ok(new_config) => {
                        let new_config = Arc::new(new_config);
                        if let Err(e) = config_sender.send(new_config) {
                            error!("Failed to send updated config: {}", e);
                            break;
                        }
                        info!("Configuration reloaded successfully");
                    }
                    Err(e) => {
                        warn!("Failed to reload configuration: {}", e);
                    }
                }
            }
        });

        self.reload_handle = Some(handle);
    }

    /// 停止配置热加载
    pub async fn stop_hot_reload(&mut self) {
        if let Some(handle) = self.reload_handle.take() {
            handle.abort();
            info!("Configuration hot reload stopped");
        }
    }

    /// 手动重新加载配置
    pub async fn reload_config(&self) -> Result<(), String> {
        let new_config = self.load_from_sources().await?;
        let new_config = Arc::new(new_config);
        self.current_config.send(new_config).map_err(|_| "Failed to send updated config")?;
        info!("Configuration manually reloaded");
        Ok(())
    }

    /// 获取当前配置
    pub fn get_current_config(&self) -> Arc<RustCloudConfig> {
        self.current_config.borrow().clone()
    }

    /// 订阅配置变更
    pub fn subscribe_config(&self) -> watch::Receiver<Arc<RustCloudConfig>> {
        self.current_config.subscribe()
    }
}

impl Drop for ConfigManager {
    fn drop(&mut self) {
        if let Some(handle) = self.reload_handle.take() {
            handle.abort();
        }
    }
}

/// 配置管理器构建器
pub struct ConfigManagerBuilder {
    sources: Vec<ConfigSource>,
    reload_interval: Duration,
}

impl ConfigManagerBuilder {
    pub fn new() -> Self {
        Self {
            sources: Vec::new(),
            reload_interval: Duration::from_secs(30),
        }
    }

    /// 添加配置源
    pub fn add_source(mut self, source: ConfigSource) -> Self {
        self.sources.push(source);
        self
    }

    /// 设置重新加载间隔
    pub fn reload_interval(mut self, interval: Duration) -> Self {
        self.reload_interval = interval;
        self
    }

    /// 构建配置管理器
    pub async fn build(self) -> Result<(ConfigManager, watch::Receiver<Arc<RustCloudConfig>>), String> {
        let (mut manager, receiver) = ConfigManager::new(self.reload_interval);

        // 添加所有配置源
        for source in self.sources {
            manager.add_source(source);
        }

        // 初始加载配置
        manager.load_config().await?;

        Ok((manager, receiver))
    }
}

impl Default for ConfigManagerBuilder {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    

    #[tokio::test]
    async fn test_config_manager_creation() {
        let (mut manager, _receiver) = ConfigManager::new(Duration::from_secs(1));
        
        // 添加内嵌配置源
        manager.add_source(ConfigSource::Embedded {
            config: RustCloudConfig::create_example_config(),
        });

        let result = manager.load_config().await;
        assert!(result.is_ok());
        let config = result.unwrap();
        assert_eq!(config.application.name, "rustcloud-gateway");
    }

    #[tokio::test]
    async fn test_config_manager_hot_reload() {
        let (mut manager, mut receiver) = ConfigManager::new(Duration::from_millis(100));
        
        manager.add_source(ConfigSource::Embedded {
            config: RustCloudConfig::create_example_config(),
        });

        manager.load_config().await.unwrap();
        manager.start_hot_reload().await;

        // 等待配置更新
        tokio::time::sleep(Duration::from_millis(200)).await;

        let config = receiver.borrow_and_update().clone();
        assert_eq!(config.application.name, "rustcloud-gateway");

        manager.stop_hot_reload().await;
    }

    #[tokio::test]
    async fn test_config_manager_builder() {
        let builder = ConfigManagerBuilder::new()
            .reload_interval(Duration::from_secs(5))
            .add_source(ConfigSource::Embedded {
                config: RustCloudConfig::create_example_config(),
            });

        let result = builder.build().await;
        assert!(result.is_ok());

        let (_manager, _receiver) = result.unwrap();
    }

    #[tokio::test]
    async fn test_manual_reload() {
        let (mut manager, _receiver) = ConfigManager::new(Duration::from_secs(1));
        
        manager.add_source(ConfigSource::Embedded {
            config: RustCloudConfig::create_example_config(),
        });

        manager.load_config().await.unwrap();
        let result = manager.reload_config().await;
        assert!(result.is_ok());
    }
}